package cn.corgy.registry.nacos.utils;

import cn.corgy.enums.RpcErrorMessageEnum;
import cn.corgy.exception.RpcException;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class NacosUtil {
    private static final int BASE_SLEEP_TIME = 1000;
    private static final int MAX_RETRIES = 3;
    private static final Map<String, List<Instance>> SERVICE_ADDRESS_MAP = new ConcurrentHashMap<>();
    private static final Set<String> REGISTERED_NAME_SET = ConcurrentHashMap.newKeySet();
    private static NamingService nacosClient;
    private static InetSocketAddress ADDRESS;
    private static final String DEFAULT_NACOS_ADDRESS = "127.0.0.1:8848";

    //获取nacos客户端
    public static NamingService getNacosClient() {
        try {
            if (nacosClient != null) return nacosClient;
            nacosClient = NamingFactory.createNamingService(DEFAULT_NACOS_ADDRESS);
            return nacosClient;
        } catch (Exception e) {
            log.error("连接到Nacos时有错误发生: ", e);
            throw new RpcException(RpcErrorMessageEnum.FAILED_TO_CONNECT_TO_SERVICE_REGISTRY);
        }
    }

    public static void registerService(NamingService nacosClient, String rpcServiceName, InetSocketAddress address) throws NacosException {
        nacosClient.registerInstance(rpcServiceName, address.getHostName(), address.getPort());
        NacosUtil.ADDRESS = address;
        REGISTERED_NAME_SET.add(rpcServiceName);

    }

    public static List<Instance> getAllInstance(NamingService nacosClient, String rpcServiceName) throws NacosException {
        if (SERVICE_ADDRESS_MAP.containsKey(rpcServiceName)) {
            return SERVICE_ADDRESS_MAP.get(rpcServiceName);
        }
        List<Instance> allInstances = nacosClient.getAllInstances(rpcServiceName);
        SERVICE_ADDRESS_MAP.put(rpcServiceName, allInstances);
        return allInstances;
    }

    public static void clearRegistry() {
        if (!REGISTERED_NAME_SET.isEmpty() && ADDRESS != null) {
            String host = ADDRESS.getHostName();
            int port = ADDRESS.getPort();
            for (String serviceName : REGISTERED_NAME_SET) {
                try {
                    nacosClient.deregisterInstance(serviceName, host, port);
                } catch (NacosException e) {
                    log.error("注销服务 {} 失败", serviceName, e);
                }
            }
        }
    }

    public static void clearRegistry(NamingService nacosClient) {
        if (nacosClient != null) REGISTERED_NAME_SET.forEach(x -> {
            List<Instance> instances = SERVICE_ADDRESS_MAP.get(x);
            instances.forEach(instance -> {
                try {
                    nacosClient.deregisterInstance(x, instance);
                } catch (NacosException e) {
                    e.printStackTrace();
                }
            });
        });
        else clearRegistry();
    }
}
